/// study 错误处理

/*

错误处理是Rust确定出错的可能性并确认在代码进行编译之前采取某些操作的机制。
此机制使程序更加健壮，因为能够在部署生产代码之前发现并处理错误。
Rust编程语言不包含异常。
Rust中有两种类型的错误：

- 不可恢复的错误。
    panic!("ssss")
- 可恢复的错误
    可恢复的错误是那些完全停止程序并不严重的错误。可以处理的错误称为可恢复错误。
    它由Result <T，E>表示。 结果<T，E>是枚举，由两个变体组成，即OK <T>和Err <E>，
    OK <T>：’T’是一种值，它在成功情况下时返回OK变量，这是一个预期的结果。
    Err <E>：’E’是一种错误，它在失败情况下时返回ERR变量，这是意想不到的结果。

可恢复的错误： 可恢复的错误是报告给用户的错误，用户可以重试该操作。
 完全停止该过 程的可恢复错误并不严重。 它由Result <T,E>，
 表示可恢复错误的示例是“找不到文件”。T＆E是通用参数。
 T->这是一种值，在成功的情况下返回一个’OK’变量。
 E->这是一种错误类型，在具有Err变体的故障情况下返回。

不可恢复的错误： 当Rust报告一个不可恢复的错误时，那就是!宏停止执行程序。例如：“除以零”是不可恢复错误的示例。
 */

// 意外的行为 assert
pub fn assert_t()
{
    let x : bool = false;
    assert!(x==true);
    //当想要声明它是真时使用。 如果它不正确和错误，则程序停止执行。
    //x的值为false，assert!断言中的条件为假。 因此，在运行时assert!调用panic!。

    //err msg : thread 'main' panicked at 'assertion failed: x == true',
}

// 意外的行为 unreachable

fn get_number()->i32
{
    5
}
pub fn unreach_t(){
    let a = match get_number()
    {
        7 => "seven",
        8=> "eight",
        _=> unreachable!()
        // unreachable! ：它用于无法访问的代码。 此宏很有用，因为编译器无法确定无法访问的代码。 在运行时由 unreachable! 执行。
    };
    println!("{}", a);
    //get_number()函数返回的值为5，它与每个模式匹配，但不与任何模式匹配。 因此，unreachable!宏调用panic!宏 。
    //err msg: thread 'main' panicked at 'internal error: entered unreachable code',
}


// 传播错误

use std::io;
use std::io::Read;
use std::fs::File;

pub fn read_username_from_file() -> Result<String, io::Error>
{
    let f = File::open("./src/err_t/a.txt");
    let mut f = match f {
        Ok(file) => file,
        Err(e) => return Err(e),
    };
    let mut s = String::new();
    match f.read_to_string(&mut s) {
        Ok(_) => Ok(s),
        Err(e) => Err(e),
    }
    // Err(Os { code: 2, kind: NotFound, message: "No such file or directory" })
}


// 传播错误的捷径：?操作符
//?运算符只能在返回Result类型值的函数中使用。 ?运算符与匹配表达式的工作方式类似。 匹配表达式仅适用于Result返回类型。

pub fn read_username_from_file2() -> Result<String, io::Error>{
    let mut f = File::open("./src/err_t/a.txt")?;
    let mut s = String::new();
    f.read_to_string(&mut s)?;
    Ok(s)
    //Err(Os { code: 2, kind: NotFound, message: "No such file or directory" })

    //使用?运算符减少了代码的长度。?运算符是匹配表达式的替换意味着?运算符的工作方式与匹配表达式的工作方式相同
    //?运算符是在Result值类型之前使用。 如果Result为OK，则返回OK变体的值，如果Result为Err，则返回错误信息。

}
pub fn read_username_from_file3() -> Result<String, io::Error>
{
    let mut s2 = String::new();
    File::open("./src/err_t/a.txt")?.read_to_string(&mut s2)?;
    Ok(s2)

    //将read_to_string()的调用链接到File::open("a.txt")?的调用结果。
    //如果两个函数(即read_to_string()和File::open("a.txt")成功，则返回OK值，否则返回错误值。

    //Err(Os { code: 2, kind: NotFound, message: "No such file or directory" })

}






